home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 21 / AACD 21.iso / AACD / Utilities / Ghostscript / src / gsline.c < prev    next >
Encoding:
C/C++ Source or Header  |  2001-01-01  |  8.4 KB  |  369 lines

  1. /* Copyright (C) 1989, 1995, 1996, 1997, 1999 Aladdin Enterprises.  All rights reserved.
  2.   
  3.   This file is part of AFPL Ghostscript.
  4.   
  5.   AFPL Ghostscript is distributed with NO WARRANTY OF ANY KIND.  No author or
  6.   distributor accepts any responsibility for the consequences of using it, or
  7.   for whether it serves any particular purpose or works at all, unless he or
  8.   she says so in writing.  Refer to the Aladdin Free Public License (the
  9.   "License") for full details.
  10.   
  11.   Every copy of AFPL Ghostscript must include a copy of the License, normally
  12.   in a plain ASCII text file named PUBLIC.  The License grants you the right
  13.   to copy, modify and redistribute AFPL Ghostscript, but only under certain
  14.   conditions described in the License.  Among other things, the License
  15.   requires that the copyright notice and this notice be preserved on all
  16.   copies.
  17. */
  18.  
  19. /*$Id: gsline.c,v 1.2 2000/09/19 19:00:29 lpd Exp $ */
  20. /* Line parameter operators for Ghostscript library */
  21. #include "math_.h"
  22. #include "memory_.h"
  23. #include "gx.h"
  24. #include "gserrors.h"
  25. #include "gxfixed.h"        /* ditto */
  26. #include "gxmatrix.h"        /* for gzstate */
  27. #include "gzstate.h"
  28. #include "gscoord.h"        /* for currentmatrix, setmatrix */
  29. #include "gsline.h"        /* for prototypes */
  30. #include "gzline.h"
  31.  
  32. /* ------ Device-independent parameters ------ */
  33.  
  34. #define pgs_lp gs_currentlineparams_inline(pgs)
  35.  
  36. /* setlinewidth */
  37. int
  38. gs_setlinewidth(gs_state * pgs, floatp width)
  39. {
  40.     gx_set_line_width(pgs_lp, width);
  41.     return 0;
  42. }
  43.  
  44. /* currentlinewidth */
  45. float
  46. gs_currentlinewidth(const gs_state * pgs)
  47. {
  48.     return gx_current_line_width(pgs_lp);
  49. }
  50.  
  51. /* setlinecap */
  52. int
  53. gs_setlinecap(gs_state * pgs, gs_line_cap cap)
  54. {
  55.     if ((uint) cap > gs_line_cap_max)
  56.     return_error(gs_error_rangecheck);
  57.     pgs_lp->cap = cap;
  58.     return 0;
  59. }
  60.  
  61. /* currentlinecap */
  62. gs_line_cap
  63. gs_currentlinecap(const gs_state * pgs)
  64. {
  65.     return pgs_lp->cap;
  66. }
  67.  
  68. /* setlinejoin */
  69. int
  70. gs_setlinejoin(gs_state * pgs, gs_line_join join)
  71. {
  72.     if ((uint) join > gs_line_join_max)
  73.     return_error(gs_error_rangecheck);
  74.     pgs_lp->join = join;
  75.     return 0;
  76. }
  77.  
  78. /* currentlinejoin */
  79. gs_line_join
  80. gs_currentlinejoin(const gs_state * pgs)
  81. {
  82.     return pgs_lp->join;
  83. }
  84.  
  85. /* setmiterlimit */
  86. int
  87. gx_set_miter_limit(gx_line_params * plp, floatp limit)
  88. {
  89.     if (limit < 1.0)
  90.     return_error(gs_error_rangecheck);
  91.     plp->miter_limit = limit;
  92.     /*
  93.      * Compute the miter check value.  The supplied miter limit is an
  94.      * upper bound on 1/sin(phi/2); we convert this to a lower bound on
  95.      * tan(phi).  Note that if phi > pi/2, this is negative.  We use the
  96.      * half-angle and angle-sum formulas here to avoid the trig functions.
  97.      * We also need a special check for phi/2 close to pi/4.
  98.      * Some C compilers can't handle this as a conditional expression....
  99.      */
  100.     {
  101.     double limit_squared = limit * limit;
  102.  
  103.     if (limit_squared < 2.0001 && limit_squared > 1.9999)
  104.         plp->miter_check = 1.0e6;
  105.     else
  106.         plp->miter_check =
  107.         sqrt(limit_squared - 1) * 2 / (limit_squared - 2);
  108.     }
  109.     return 0;
  110. }
  111. int
  112. gs_setmiterlimit(gs_state * pgs, floatp limit)
  113. {
  114.     return gx_set_miter_limit(pgs_lp, limit);
  115. }
  116.  
  117. /* currentmiterlimit */
  118. float
  119. gs_currentmiterlimit(const gs_state * pgs)
  120. {
  121.     return pgs_lp->miter_limit;
  122. }
  123.  
  124. /* setdash */
  125. int
  126. gx_set_dash(gx_dash_params * dash, const float *pattern, uint length,
  127.         floatp offset, gs_memory_t * mem)
  128. {
  129.     uint n = length;
  130.     const float *dfrom = pattern;
  131.     bool ink = true;
  132.     int index = 0;
  133.     float pattern_length = 0.0;
  134.     float dist_left;
  135.     float *ppat = dash->pattern;
  136.  
  137.     /* Check the dash pattern. */
  138.     while (n--) {
  139.     float elt = *dfrom++;
  140.  
  141.     if (elt < 0)
  142.         return_error(gs_error_rangecheck);
  143.     pattern_length += elt;
  144.     }
  145.     if (length == 0) {        /* empty pattern */
  146.     dist_left = 0.0;
  147.     if (mem && ppat) {
  148.         gs_free_object(mem, ppat, "gx_set_dash(old pattern)");
  149.         ppat = 0;
  150.     }
  151.     } else {
  152.     uint size = length * sizeof(float);
  153.  
  154.     if (pattern_length == 0)
  155.         return_error(gs_error_rangecheck);
  156.     /* Compute the initial index, ink_on, and distance left */
  157.     /* in the pattern, according to the offset. */
  158. #define f_mod(a, b) ((a) - floor((a) / (b)) * (b))
  159.     if (length & 1) {    /* Odd and even repetitions of the pattern */
  160.         /* have opposite ink values! */
  161.         float length2 = pattern_length * 2;
  162.  
  163.         dist_left = f_mod(offset, length2);
  164.         if (dist_left >= pattern_length)
  165.         dist_left -= pattern_length, ink = !ink;
  166.     } else
  167.         dist_left = f_mod(offset, pattern_length);
  168.     while ((dist_left -= pattern[index]) >= 0 &&
  169.            (dist_left > 0 || pattern[index] != 0)
  170.         )
  171.         ink = !ink, index++;
  172.     if (mem) {
  173.         if (ppat == 0)
  174.         ppat = (float *)gs_alloc_bytes(mem, size,
  175.                            "gx_set_dash(pattern)");
  176.         else if (length != dash->pattern_size)
  177.         ppat = gs_resize_object(mem, ppat, size,
  178.                     "gx_set_dash(pattern)");
  179.         if (ppat == 0)
  180.         return_error(gs_error_VMerror);
  181.     }
  182.     memcpy(ppat, pattern, length * sizeof(float));
  183.     }
  184.     dash->pattern = ppat;
  185.     dash->pattern_size = length;
  186.     dash->offset = offset;
  187.     dash->pattern_length = pattern_length;
  188.     dash->init_ink_on = ink;
  189.     dash->init_index = index;
  190.     dash->init_dist_left = -dist_left;
  191.     return 0;
  192. }
  193. int
  194. gs_setdash(gs_state * pgs, const float *pattern, uint length, floatp offset)
  195. {
  196.     return gx_set_dash(&pgs_lp->dash, pattern, length, offset,
  197.                pgs->memory);
  198. }
  199.  
  200. /* currentdash */
  201. uint
  202. gs_currentdash_length(const gs_state * pgs)
  203. {
  204.     return pgs_lp->dash.pattern_size;
  205. }
  206. const float *
  207. gs_currentdash_pattern(const gs_state * pgs)
  208. {
  209.     return pgs_lp->dash.pattern;
  210. }
  211. float
  212. gs_currentdash_offset(const gs_state * pgs)
  213. {
  214.     return pgs_lp->dash.offset;
  215. }
  216.  
  217. /* Internal accessor for line parameters */
  218. const gx_line_params *
  219. gs_currentlineparams(const gs_imager_state * pis)
  220. {
  221.     return gs_currentlineparams_inline(pis);
  222. }
  223.  
  224. /* ------ Device-dependent parameters ------ */
  225.  
  226. /* setflat */
  227. int
  228. gs_imager_setflat(gs_imager_state * pis, floatp flat)
  229. {
  230.     if (flat <= 0.2)
  231.     flat = 0.2;
  232.     else if (flat > 100)
  233.     flat = 100;
  234.     pis->flatness = flat;
  235.     return 0;
  236. }
  237. int
  238. gs_setflat(gs_state * pgs, floatp flat)
  239. {
  240.     return gs_imager_setflat((gs_imager_state *) pgs, flat);
  241. }
  242.  
  243. /* currentflat */
  244. float
  245. gs_currentflat(const gs_state * pgs)
  246. {
  247.     return pgs->flatness;
  248. }
  249.  
  250. /* setstrokeadjust */
  251. int
  252. gs_setstrokeadjust(gs_state * pgs, bool stroke_adjust)
  253. {
  254.     pgs->stroke_adjust = stroke_adjust;
  255.     return 0;
  256. }
  257.  
  258. /* currentstrokeadjust */
  259. bool
  260. gs_currentstrokeadjust(const gs_state * pgs)
  261. {
  262.     return pgs->stroke_adjust;
  263. }
  264.  
  265. /* ------ Extensions ------ */
  266.  
  267. /* Device-independent */
  268.  
  269. /* setdashadapt */
  270. void
  271. gs_setdashadapt(gs_state * pgs, bool adapt)
  272. {
  273.     pgs_lp->dash.adapt = adapt;
  274. }
  275.  
  276. /* currentdashadapt */
  277. bool
  278. gs_imager_currentdashadapt(const gs_imager_state * pis)
  279. {
  280.     return gs_currentlineparams_inline(pis)->dash.adapt;
  281. }
  282. bool
  283. gs_currentdashadapt(const gs_state * pgs)
  284. {
  285.     return gs_imager_currentdashadapt((const gs_imager_state *)pgs);
  286. }
  287.  
  288. /* setcurvejoin */
  289. int
  290. gs_setcurvejoin(gs_state * pgs, int join)
  291. {
  292.     if (join < -1 || join > gs_line_join_max)
  293.     return_error(gs_error_rangecheck);
  294.     pgs_lp->curve_join = join;
  295.     return 0;
  296. }
  297.  
  298. /* currentcurvejoin */
  299. int
  300. gs_currentcurvejoin(const gs_state * pgs)
  301. {
  302.     return pgs_lp->curve_join;
  303. }
  304.  
  305. /* Device-dependent */
  306.  
  307. /* setaccuratecurves */
  308. void
  309. gs_setaccuratecurves(gs_state * pgs, bool accurate)
  310. {
  311.     pgs->accurate_curves = accurate;
  312. }
  313.  
  314. /* currentaccuratecurves */
  315. bool
  316. gs_imager_currentaccuratecurves(const gs_imager_state * pis)
  317. {
  318.     return pis->accurate_curves;
  319. }
  320. bool
  321. gs_currentaccuratecurves(const gs_state * pgs)
  322. {
  323.     return gs_imager_currentaccuratecurves((const gs_imager_state *)pgs);
  324. }
  325.  
  326. /* setdotlength */
  327. int
  328. gx_set_dot_length(gx_line_params * plp, floatp length, bool absolute)
  329. {
  330.     if (length < 0)
  331.     return_error(gs_error_rangecheck);
  332.     plp->dot_length = length;
  333.     plp->dot_length_absolute = absolute;
  334.     return 0;
  335. }
  336. int
  337. gs_setdotlength(gs_state * pgs, floatp length, bool absolute)
  338. {
  339.     return gx_set_dot_length(pgs_lp, length, absolute);
  340. }
  341.  
  342. /* currentdotlength */
  343. float
  344. gs_currentdotlength(const gs_state * pgs)
  345. {
  346.     return pgs_lp->dot_length;
  347. }
  348. bool
  349. gs_currentdotlength_absolute(const gs_state * pgs)
  350. {
  351.     return pgs_lp->dot_length_absolute;
  352. }
  353.  
  354. /* setdotorientation */
  355. int
  356. gs_setdotorientation(gs_state *pgs)
  357. {
  358.     if (is_xxyy(&pgs->ctm) || is_xyyx(&pgs->ctm))
  359.     return gs_currentmatrix(pgs, &pgs_lp->dot_orientation);
  360.     return_error(gs_error_rangecheck);
  361. }
  362.  
  363. /* dotorientation */
  364. int
  365. gs_dotorientation(gs_state *pgs)
  366. {
  367.     return gs_setmatrix(pgs, &pgs_lp->dot_orientation);
  368. }
  369.